package com.imut.lagain.repository;
import org.slf4j.LoggerFactory;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.imut.lagain.entity.MemoryEntry;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 记忆条目数据访问层
 */
@Mapper
public interface MemoryEntryRepository extends BaseMapper<MemoryEntry> {
    
    /**
     * 根据胶囊ID查询条目列表
     * @param capsuleId 胶囊ID
     * @return 条目列表
     */
    @Select("SELECT * FROM memory_entry WHERE capsule_id = #{capsuleId} AND is_deleted = 0 ORDER BY sort_order ASC, create_time ASC")
    List<MemoryEntry> findByCapsuleId(@Param("capsuleId") Long capsuleId);
    
    /**
     * 根据胶囊ID分页查询条目列表
     * @param capsuleId 胶囊ID
     * @param page 分页参数
     * @return 条目分页列表
     */
    @Select("SELECT * FROM memory_entry WHERE capsule_id = #{capsuleId} AND is_deleted = 0 ORDER BY sort_order ASC, create_time ASC")
    IPage<MemoryEntry> findByCapsuleIdWithPage(@Param("capsuleId") Long capsuleId, Page<MemoryEntry> page);
    
    /**
     * 根据条目类型查询条目列表
     * @param type 条目类型
     * @param page 分页参数
     * @return 条目分页列表
     */
    @Select("SELECT * FROM memory_entry WHERE type = #{type} AND is_deleted = 0 ORDER BY create_time DESC")
    IPage<MemoryEntry> findByType(@Param("type") Integer type, Page<MemoryEntry> page);
    
    /**
     * 根据条目类型查询条目列表
     * @param entryType 条目类型
     * @return 条目列表
     */
    @Select("SELECT * FROM memory_entry WHERE entry_type = #{entryType} AND is_deleted = 0 ORDER BY create_time DESC")
    List<MemoryEntry> findByEntryType(@Param("entryType") String entryType);
    
    /**
     * 根据条目类型分页查询条目列表
     * @param entryType 条目类型
     * @param page 分页参数
     * @return 条目分页列表
     */
    @Select("SELECT * FROM memory_entry WHERE entry_type = #{entryType} AND is_deleted = 0 ORDER BY create_time DESC")
    IPage<MemoryEntry> findByEntryType(@Param("entryType") String entryType, Page<MemoryEntry> page);
    
    /**
     * 根据条目类型分页查询条目列表
     * @param entryType 条目类型
     * @param page 分页参数
     * @return 条目分页列表
     */
    @Select("SELECT * FROM memory_entry WHERE entry_type = #{entryType} AND is_deleted = 0 ORDER BY create_time DESC")
    IPage<MemoryEntry> findByEntryTypeWithPage(@Param("entryType") String entryType, Page<MemoryEntry> page);
    
    /**
     * 根据胶囊ID和条目类型查询条目列表
     * @param capsuleId 胶囊ID
     * @param type 条目类型
     * @return 条目列表
     */
    @Select("SELECT * FROM memory_entry WHERE capsule_id = #{capsuleId} AND type = #{type} AND is_deleted = 0 ORDER BY sort_order ASC, create_time ASC")
    List<MemoryEntry> findByCapsuleIdAndType(@Param("capsuleId") Long capsuleId, @Param("type") Integer type);
    
    /**
     * 根据胶囊ID和条目类型查询条目列表
     * @param capsuleId 胶囊ID
     * @param entryType 条目类型
     * @return 条目列表
     */
    @Select("SELECT * FROM memory_entry WHERE capsule_id = #{capsuleId} AND entry_type = #{entryType} AND is_deleted = 0 ORDER BY sort_order ASC, create_time ASC")
    List<MemoryEntry> findByCapsuleIdAndEntryType(@Param("capsuleId") Long capsuleId, @Param("entryType") String entryType);
    
    /**
     * 根据胶囊ID和条目类型分页查询条目列表
     * @param capsuleId 胶囊ID
     * @param entryType 条目类型
     * @param page 分页参数
     * @return 条目分页列表
     */
    @Select("SELECT * FROM memory_entry WHERE capsule_id = #{capsuleId} AND entry_type = #{entryType} AND is_deleted = 0 ORDER BY sort_order ASC, create_time ASC")
    IPage<MemoryEntry> findByCapsuleIdAndType(@Param("capsuleId") Long capsuleId, @Param("entryType") String entryType, Page<MemoryEntry> page);
    
    /**
     * 根据文件URL查询条目
     * @param fileUrl 文件URL
     * @return 条目信息
     */
    @Select("SELECT * FROM memory_entry WHERE file_url = #{fileUrl} AND is_deleted = 0")
    MemoryEntry findByFileUrl(@Param("fileUrl") String fileUrl);
    
    /**
     * 统计胶囊中的条目数量
     * @param capsuleId 胶囊ID
     * @return 条目数量
     */
    @Select("SELECT COUNT(*) FROM memory_entry WHERE capsule_id = #{capsuleId} AND is_deleted = 0")
    Long countByCapsuleId(@Param("capsuleId") Long capsuleId);
    
    /**
     * 统计胶囊中指定类型的条目数量
     * @param capsuleId 胶囊ID
     * @param type 条目类型
     * @return 条目数量
     */
    @Select("SELECT COUNT(*) FROM memory_entry WHERE capsule_id = #{capsuleId} AND type = #{type} AND is_deleted = 0")
    Long countByCapsuleIdAndType(@Param("capsuleId") Long capsuleId, @Param("type") Integer type);
    
    /**
     * 统计指定类型的条目总数
     * @param type 条目类型
     * @return 条目数量
     */
    @Select("SELECT COUNT(*) FROM memory_entry WHERE type = #{type} AND is_deleted = 0")
    Long countByType(@Param("type") Integer type);
    
    /**
     * 获取胶囊中条目的最大排序值
     * @param capsuleId 胶囊ID
     * @return 最大排序值
     */
    @Select("SELECT COALESCE(MAX(sort_order), 0) FROM memory_entry WHERE capsule_id = #{capsuleId} AND is_deleted = 0")
    Integer getMaxSortOrderByCapsuleId(@Param("capsuleId") Long capsuleId);
    
    /**
     * 更新条目排序
     * @param entryId 条目ID
     * @param sortOrder 新排序值
     * @return 影响行数
     */
    @Update("UPDATE memory_entry SET sort_order = #{sortOrder}, update_time = NOW() WHERE id = #{entryId}")
    int updateSortOrder(@Param("entryId") Long entryId, @Param("sortOrder") Integer sortOrder);
    
    /**
     * 批量更新条目排序
     * @param entryIds 条目ID列表
     * @param sortOrders 对应的排序值列表
     * @return 影响行数
     */
    @Update("<script>" +
            "<foreach collection='entryIds' item='entryId' index='index'>" +
            "UPDATE memory_entry SET sort_order = #{sortOrders[${index}]}, update_time = NOW() WHERE id = #{entryId};" +
            "</foreach>" +
            "</script>")
    int batchUpdateSortOrder(@Param("entryIds") List<Long> entryIds, @Param("sortOrders") List<Integer> sortOrders);
    
    /**
     * 根据内容模糊查询条目
     * @param content 内容关键字
     * @param page 分页参数
     * @return 条目分页列表
     */
    @Select("SELECT * FROM memory_entry WHERE content LIKE CONCAT('%', #{content}, '%') AND is_deleted = 0 ORDER BY create_time DESC")
    IPage<MemoryEntry> findByContentLike(@Param("content") String content, Page<MemoryEntry> page);
    
    /**
     * 在指定胶囊中根据内容模糊查询条目
     * @param capsuleId 胶囊ID
     * @param content 内容关键字
     * @return 条目列表
     */
    @Select("SELECT * FROM memory_entry WHERE capsule_id = #{capsuleId} AND content LIKE CONCAT('%', #{content}, '%') AND is_deleted = 0 ORDER BY sort_order ASC, create_time ASC")
    List<MemoryEntry> findByCapsuleIdAndContentLike(@Param("capsuleId") Long capsuleId, @Param("content") String content);
    
    /**
     * 查询指定时间范围内创建的条目
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 条目列表
     */
    @Select("SELECT * FROM memory_entry WHERE create_time BETWEEN #{startTime} AND #{endTime} AND is_deleted = 0 ORDER BY create_time DESC")
    List<MemoryEntry> findByCreateTimeBetween(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);
    
    /**
     * 查询指定时间范围内创建的条目（分页）
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param page 分页参数
     * @return 条目分页列表
     */
    @Select("SELECT * FROM memory_entry WHERE create_time BETWEEN #{startTime} AND #{endTime} AND is_deleted = 0 ORDER BY create_time DESC")
    IPage<MemoryEntry> findByCreateTimeBetween(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, Page<MemoryEntry> page);
    
    /**
     * 根据用户ID和时间范围查询条目（分页）
     * @param userId 用户ID
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param page 分页参数
     * @return 条目分页列表
     */
    @Select("SELECT me.* FROM memory_entry me " +
            "INNER JOIN memory_capsule mc ON me.capsule_id = mc.id " +
            "WHERE mc.user_id = #{userId} AND me.create_time BETWEEN #{startTime} AND #{endTime} " +
            "AND me.is_deleted = 0 AND mc.is_deleted = 0 ORDER BY me.create_time DESC")
    IPage<MemoryEntry> findByUserIdAndCreateTimeBetween(@Param("userId") Long userId, @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, Page<MemoryEntry> page);
    
    /**
     * 查询包含文件的条目列表
     * @param page 分页参数
     * @return 条目分页列表
     */
    @Select("SELECT * FROM memory_entry WHERE file_url IS NOT NULL AND file_url != '' AND is_deleted = 0 ORDER BY create_time DESC")
    IPage<MemoryEntry> findEntriesWithFiles(Page<MemoryEntry> page);
    
    /**
     * 统计包含文件的条目数量
     * @return 条目数量
     */
    @Select("SELECT COUNT(*) FROM memory_entry WHERE file_url IS NOT NULL AND file_url != '' AND is_deleted = 0")
    Long countEntriesWithFiles();
    
    /**
     * 统计包含文件的条目数量（按胶囊ID）
     * @param capsuleId 胶囊ID
     * @return 条目数量
     */
    /*
    @Select("<script>" +
            "SELECT COUNT(*) FROM memory_entry WHERE file_url IS NOT NULL AND file_url != '' AND is_deleted = 0" +
            "<if test='capsuleId != null'> AND capsule_id = #{capsuleId}</if>" +
            "</script>")
    Long countEntriesWithFiles(@Param("capsuleId") Long capsuleId);
    */
    
    /**
     * 根据用户ID查询所有记忆条目
     * @param userId 用户ID
     * @return 条目列表
     */
    @Select("SELECT me.* FROM memory_entry me " +
            "INNER JOIN memory_capsule mc ON me.capsule_id = mc.id " +
            "WHERE mc.user_id = #{userId} AND me.is_deleted = 0 AND mc.is_deleted = 0 " +
            "ORDER BY me.create_time DESC")
    List<MemoryEntry> findByUserId(@Param("userId") Long userId);
    
    /**
     * 统计条目数量
     * @param capsuleId 胶囊ID（null表示所有胶囊）
     * @param entryType 条目类型（null表示所有类型）
     * @param hasFile 是否包含文件（null表示所有）
     * @return 条目数量
     */
    /*
    @Select("<script>" +
            "SELECT COUNT(*) FROM memory_entry WHERE is_deleted = 0" +
            "<if test='capsuleId != null'> AND capsule_id = #{capsuleId}</if>" +
            "<if test='entryType != null and entryType != \"\"'> AND entry_type = #{entryType}</if>" +
            "<if test='hasFile != null and hasFile == true'> AND file_url IS NOT NULL AND file_url != ''</if>" +
            "<if test='hasFile != null and hasFile == false'> AND (file_url IS NULL OR file_url = '')</if>" +
            "</script>")
    Long countEntries(@Param("capsuleId") Long capsuleId, @Param("entryType") String entryType, @Param("hasFile") Boolean hasFile);
    */
    
    /**
     * 在指定胶囊中根据内容模糊查询条目（分页）
     * @param capsuleId 胶囊ID
     * @param content 内容关键字
     * @param page 分页参数
     * @return 条目分页列表
     */
    @Select("SELECT * FROM memory_entry WHERE capsule_id = #{capsuleId} AND content LIKE CONCAT('%', #{content}, '%') AND is_deleted = 0 ORDER BY sort_order ASC, create_time ASC")
    IPage<MemoryEntry> findByContentLikeInCapsule(@Param("capsuleId") Long capsuleId, @Param("content") String content, Page<MemoryEntry> page);
    
    /**
     * 根据文件类型查询条目
     * @param fileType 文件类型
     * @param page 分页参数
     * @return 条目分页列表
     */
    @Select("SELECT * FROM memory_entry WHERE file_type = #{fileType} AND is_deleted = 0 ORDER BY create_time DESC")
    IPage<MemoryEntry> findByFileType(@Param("fileType") String fileType, Page<MemoryEntry> page);
    
    /**
     * 搜索记忆条目
     * @param userId 用户ID
     * @param keyword 搜索关键词
     * @param capsuleId 胶囊ID（可选）
     * @param page 分页参数
     * @return 搜索结果分页列表
     */
    @Select("<script>" +
            "SELECT me.* FROM memory_entry me " +
            "INNER JOIN memory_capsule mc ON me.capsule_id = mc.id " +
            "WHERE mc.user_id = #{userId} AND me.is_deleted = 0 AND mc.is_deleted = 0" +
            "<if test='keyword != null and keyword != \"\"\'> AND me.content LIKE CONCAT('%', #{keyword}, '%')</if>" +
            "<if test='capsuleId != null'> AND me.capsule_id = #{capsuleId}</if>" +
            " ORDER BY me.create_time DESC" +
            "</script>")
    IPage<MemoryEntry> searchEntries(@Param("userId") Long userId, @Param("keyword") String keyword, @Param("capsuleId") Long capsuleId, Page<MemoryEntry> page);

    IPage<MemoryEntry> findWithFiles(Page<MemoryEntry> page);

    IPage<MemoryEntry> findWithFilesByUserId(Long userId, Page<MemoryEntry> page);
}
